package com.threadPool;


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

public class MyThreadPool {


    private final int corePoolSize;

    private final int maxSize;

    private final int timeout;

    private final TimeUnit timeUnit;

    private final RejectHandle rejectHandle;

    // 用阻塞队列存储任务
    private final ArrayBlockingQueue<Runnable> blockingDeque;

    public MyThreadPool(int corePoolSize, int maxSize , int timeout, TimeUnit timeUnit, ArrayBlockingQueue blockingDeque,RejectHandle rejectHandle){
        this.corePoolSize = corePoolSize;
        this.maxSize = maxSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        this.blockingDeque = blockingDeque;
        this.rejectHandle = rejectHandle;
    }



//    List<Runnable> runnableList = new ArrayList<>();

    // 当线程池只有一个线程
//    Thread thread = new Thread(()->{
//        //如果不是阻塞队列而是普通的队列进行存储，那么在元素为空时会无意义的消耗资源
////        while(true){
////            if(!runnableList.isEmpty()){
////                Runnable runnable = runnableList.remove(0);
////                runnable.run();
////            }
////        }
//
//        while (true){
//            Runnable command = null;
//            try {
//                // 当队列元素为空时，这条语句会被阻塞，防止无意义的消耗资源
//                command = blockingDeque.take();
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            command.run();
//        }
//    },("unique thread"));
//
//    {
//        thread.start();
//    }


    // 线程复用的逻辑：想让一个线程反复执行不同的runnable任务，只能对Runnable处理
    // Runnable中重复执行不同的runnable对象
//    private final Runnable coreTask = ()->{
//        while (true){
//            Runnable command = null;
//            try {
//                // 当队列元素为空时，这条语句会被阻塞，防止无意义的消耗资源
//                command = blockingDeque.take();
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            command.run();
//        }
//    };

    // 线程复用的核心逻辑，在run方法中执行不同的runnable
    class coreThread extends Thread{
        @Override
        public void run() {
            while (true){
                Runnable command = null;
                try {
                    // 当队列元素为空时，这条语句会被阻塞，防止无意义的消耗资源
                    command = blockingDeque.take();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                command.run();
            }
        }
    }

//    private final Runnable supportTask = ()->{
//        while (true){
//            Runnable command = null;
//            try {
//                // 当队列元素为空时，这条语句会被阻塞，防止无意义的消耗资源
//                command = blockingDeque.poll(1, TimeUnit.SECONDS);
//                if(command == null){
//                    break;
//                }
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            command.run();
//        }
//        System.out.println(Thread.currentThread().getName() + "is overed");
//    };

    class SupportThread extends Thread{
        @Override
        public void run() {
            while (true){
                Runnable command = null;
                try {
                    // 当队列元素为空时，这条语句会被阻塞，防止无意义的消耗资源
                    // poll 会在设置时间阻塞，当阻塞时间到了，会自动结束阻塞，返回null
                    command = blockingDeque.poll(timeout,timeUnit);
                    if(command == null){
                        break;
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                command.run();
            }
            System.out.println(Thread.currentThread().getName() + "is overed");
        }
    }




    List<Thread> coreList = new ArrayList<>();
    List<Thread> supportList = new ArrayList<>();

    void excute(Runnable command){
        if(coreList.size() < corePoolSize){
            Thread thread = new coreThread();
            coreList.add(thread);
            thread.start();
        }

        // offer添加元素有返回值（判断是否添加成功），add没有，但是容量满了会抛出异常
//        boolean offer = blockingDeque.offer(command);
        if(blockingDeque.offer(command)){
            return;
        }

        if(coreList.size() + supportList.size() < maxSize){
            Thread thread = new SupportThread();
            supportList.add(thread);
            thread.start();;
        }
        if(!blockingDeque.offer(command)){
            rejectHandle.reject(command,this);
        }
    }
}
